package at.fhooe.stefanirndorfer.logging;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Log {

	public enum Level {
		DEBUG(0, 'D'), INFO(1, 'I'), WARNING(2, 'W'), ERROR(3, 'E');

		private final int m_level;
		private final char m_prefix;

		private Level(int level, char prefix) {
			m_level = level;
			m_prefix = prefix;
		}

		private int getLevel() {
			return m_level;
		}

		private char getPrefix() {
			return m_prefix;
		}
	}

	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
			"HH:mm:ss.SSS");
	private static final String LOG_FILE = "Log.txt";

	private static Level s_displayLevel = Level.INFO;

	/**
	 * Sets the lowest Log Level to display on the console. The order is DEBUG,
	 * INFO, WARNING, ERROR. Default is INFO.
	 * 
	 * @param displayLevel
	 *            The lowest level to display
	 */
	public static void setDisplayLevel(Level displayLevel) {
		s_displayLevel = displayLevel;
	}

	/**
	 * Clears the console and removes the log file.
	 */
	public static void clear() {
		try {
			Runtime.getRuntime().exec("cls");
		} catch (IOException e) {
		}
		if (LOG_FILE != null) {
			File f = new File(LOG_FILE);
			if (f.exists() && !f.isDirectory() && f.canWrite())
				f.delete();
		}
	}

	/**
	 * Displays debug information. Writes to log file.
	 * 
	 * @param sender
	 *            Usually the "this" object, the instance who calls the Logger.
	 * @param message
	 *            The message you want to display.
	 */
	public static void debug(Object sender, String message) {
		write(sender, Level.DEBUG, message);
	}

	/**
	 * Displays information. Writes to log file.
	 * 
	 * @param sender
	 *            Usually the "this" object, the instance who calls the Logger.
	 * @param message
	 *            The message you want to display.
	 */
	public static void info(Object sender, String message) {
		write(sender, Level.INFO, message);
	}

	/**
	 * Displays warning. Writes to log file.
	 * 
	 * @param sender
	 *            Usually the "this" object, the instance who calls the Logger.
	 * @param message
	 *            The message you want to display.
	 */
	public static void warning(Object sender, String message) {
		write(sender, Level.WARNING, message);
	}

	/**
	 * Displays error. Writes to log file.
	 * 
	 * @param sender
	 *            Usually the "this" object, the instance who calls the Logger.
	 * @param message
	 *            The message you want to display.
	 */
	public static void error(Object sender, String message) {
		write(sender, Level.ERROR, message);
	}

	@SuppressWarnings("rawtypes")
	private static String getSender(Object sender) {
		if (sender instanceof Class) {
			return ((Class) sender).getCanonicalName();
		} else {
			return sender.getClass().getCanonicalName();
		}
	}

	private static void write(Object sender, Level level, String message) {

		String output = "(" + level.getPrefix() + ") ";
		output += DATE_FORMAT.format(new Date()) + ": ";
		output += getSender(sender) + ":\n";
		output += "\t" + message.replace("\n", "\n\t");

		if (level.getLevel() >= s_displayLevel.getLevel()) {
			if (level.getLevel() < Level.ERROR.getLevel()) {
				System.out.println(output);
			} else {
				System.err.println(output);
			}
		}

		writeToLogFile(output);
	}

	private static void writeToLogFile(String output) {
		if (LOG_FILE != null) {
			try {
				PrintWriter out = new PrintWriter(new BufferedWriter(
						new FileWriter(LOG_FILE, true)));
				out.println(output);
				out.close();
			} catch (IOException e) {
			}
		}
	}

}
